package jia;

import jason.asSemantics.TransitionSystem;

import java.awt.Point;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.TreeSet;

public class ConnectedComponents {
	
	
	
	public static CowCluster[] getClusters(TransitionSystem ts, int[][] input, int connectionRange, int maxClusterSize) {
		
		int[][] components = new int[input.length][input[0].length];
		
		ArrayList<int[]> equivalenceTable = new ArrayList<int[]>();
		int label = 1;
		
		for (int y = 0; y < input[0].length; y++) {
			for (int x = 0; x < input.length; x++) {
				
				
				if (input[x][y] > 0) {
					TreeSet<Integer> found = new TreeSet<Integer>();
					
					
					int n = connectionRange;
					for (int j = -n; j <= 0; j++) {
						for (int i = -n; i <= n; i++) {
							if (i > 0 && i > j * -1 || (i == 0 && j == 0))
								continue;
							
							if (x+i >= 0 && y+j >= 0 && x+i < input.length && y+j < input[0].length)
								if (input[x+i][y+j] > 0)
									found.add(components[x+i][y+j]);
						}
					}
					
					if (found.size() == 0) {
						components[x][y] = label;
						label++;
					} else {
						components[x][y] = found.first();
						
						if (found.size() > 1) {
							int low = found.first();
							found.remove(low);
							
							while (found.size() > 0) {
								int elem = found.first();
								found.remove(elem);
								equivalenceTable.add(new int[] {low, elem});
							} // while
						} // if
					} // else
					
				} // if
				
			} // for
		} // for
		
		
		// apply equivalence table
		for (int[] i : equivalenceTable) {
			for (int x = 0; x < input.length; x++) {
				for (int y = 0; y < input[0].length; y++) {
					if (components[x][y] == i[1]) {
						components[x][y] = i[0];
					}
				}
			}
		}
		
		// split large clusters
		label++;
		TreeSet<Integer> found = new TreeSet<Integer>();
		
		for (int x = 0; x < input.length; x++) {
			for (int y = 0; y < input[0].length; y++) {
				if (input[x][y] > 0)
					found.add(components[x][y]);
			}
		}
		
		while (found.size() > 0) {
			int elem = found.first();
			if (countOccurrences(components, elem) > maxClusterSize) {
				
				int c = 1;
				for (int x = 0; x < input.length; x++) {
					for (int y = 0; y < input[0].length; y++) {
						if (components[x][y] == elem) {
							if (c % maxClusterSize == 0)
								label++;
							
							components[x][y] = label;
							c++;
						}
					}
				}
				
			}
			
			found.remove(elem);
		}
		
		
		
		
		// create cow clusters
		HashMap<Integer,CowCluster> clusters = new HashMap<Integer,CowCluster>();
		for (int x = 0; x < input.length; x++) {
			for (int y = 0; y < input[0].length; y++) {
				if (components[x][y] == 0)
					continue;
				
				if (clusters.containsKey(components[x][y])) {
					clusters.get(components[x][y]).addCow(x,y);
				}
				else {
					clusters.put(components[x][y], new CowCluster());
					clusters.get(components[x][y]).addCow(x,y);
				}
			}
		}
		
		
		// calculating mean and std
		CowCluster[] foundClusters = new CowCluster[clusters.size()];
		int i = 0;
		for (CowCluster c : clusters.values()) {
			c.calcMeanAndStdDev();
			foundClusters[i] = c;
			i++;
		}
		
		return foundClusters;
	}
	
	
	public static int countOccurrences(int[][] components, int number) {
		int count = 0;
		for (int y = 0; y < components[0].length; y++) {
			for (int x = 0; x < components.length; x++) {
				if (components[x][y] == number)
					count++;
			}
		}
		
		return count;
	}
	
	
}